spacepaste

  1.  
  2. #define F_CPU 8000000UL
  3. #include <avr/io.h>
  4. #include <stdio.h>
  5. #include <inttypes.h>
  6. #include <stdint.h>
  7. #include <avr/pgmspace.h>
  8. #include <avr/interrupt.h>
  9. #include <util/delay.h>
  10. #include <util/atomic.h>
  11. #include <avr/wdt.h>
  12. #define BAUDRATE 9600
  13. #define NTCBETA 3380
  14. #define NTCRES 10000
  15. #define NTCFIXEDRES 10000
  16. #define ONTEMP 4.0 // °C
  17. #define OFFTEMP 2.0 // °C
  18. #define POWERONDELAY 10 // sec
  19. #define ONTIME 60 // sec
  20. #define OFFTIME 180 // sec
  21. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. // attiny48 //
  23. // pins //
  24. // 1 : PB5 reset, ADC0 //
  25. // 2 : PB3 ADC3 / RELAY //
  26. // 3 : PB4 ADC2 / CAP //
  27. // 4 : gnd //
  28. // 5 : PB0 Mosi, AREF //
  29. // 6 : PB1 Miso / TX //
  30. // 7 : PB2 SCK, ADC1 / NTC //
  31. // 8 : VCC //
  32. // //
  33. // VCC -> 10k -> NTC -> GND //
  34. // NTC: NTSD1XH103FPB40 https://media.digikey.com/pdf/Data%20Sheets/Murata%20PDFs/NTSD1%20Spec.pdf //
  35. // Beta: 3380 //
  36. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. #define RELAYPIN PINB
  38. #define RELAYDDR DDRB
  39. #define RELAYPORT PORTB
  40. #define RELAYBIT 3
  41. #define CAPPIN PINB
  42. #define CAPDDR DDRB
  43. #define CAPPORT PORTB
  44. #define CAPBIT 4
  45. #define NTCPIN PINB
  46. #define NTCPORT PORTB
  47. #define NTCDDR DDRB
  48. #define NTCMUX 1
  49. #define NTCBIT 2
  50. #define UARTTXPIN PINB
  51. #define UARTTXPORT PORTB
  52. #define UARTTXDDR DDRB
  53. #define UARTTXBIT 1
  54. ////////////////////////
  55. // Do not edit bellow //
  56. ////////////////////////
  57. volatile uint32_t timeSecs = 0;
  58. volatile uint32_t timeCycles = 0;
  59. volatile uint8_t status = 0;
  60. volatile uint16_t timeStatus = 0;
  61. volatile float temperature = 0.0;
  62. void usart_bitdelay() {
  63. _delay_us(1000000/BAUDRATE); // 1e6 us / baudrate
  64. }
  65. void usart_putchar(char data) {
  66. // 0 start, LSB...MSB, 1 stop
  67. uint8_t i;
  68. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  69. // start bit, 0
  70. UARTTXPORT &= ~(1 << UARTTXBIT);
  71. usart_bitdelay();
  72. // 8 data bits
  73. for (i = 0; i <= 7; i++) {
  74. if (data & 0x01) {
  75. // 1
  76. UARTTXPORT |= (1 << UARTTXBIT);
  77. } else {
  78. // 0
  79. UARTTXPORT &= ~(1 << UARTTXBIT);
  80. }
  81. data = (data >> 1);
  82. usart_bitdelay();
  83. }
  84. // stop bit, 1
  85. UARTTXPORT |= (1 << UARTTXBIT);
  86. usart_bitdelay();
  87. usart_bitdelay();
  88. }
  89. }
  90. static FILE mystdout = FDEV_SETUP_STREAM(usart_putchar, NULL, _FDEV_SETUP_WRITE);
  91. void getTemp() {
  92. }
  93. void printData() {
  94. uint32_t lsecs;
  95. uint16_t lhours;
  96. uint8_t lmins;
  97. uint8_t lstatus;
  98. uint16_t ltstatus;
  99. float ltemp;
  100. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  101. lsecs = timeSecs;
  102. lstatus = status;
  103. ltstatus = timeStatus;
  104. ltemp = temperature;
  105. };
  106. lhours = lsecs / 3600;
  107. lsecs = lsecs - (lhours * 3600);
  108. lmins = lsecs / 60;
  109. lsecs = lsecs - (lmins * 60);
  110. printf_P(PSTR("% 5d:%02d:%02d "), lhours, lmins, lsecs);
  111. //printf_P(PSTR("Temperature: % 6.1f°C "), ltemp);
  112. printf_P(PSTR("Temperature: %f°C "), ltemp);
  113. printf_P(PSTR("Status: %d "), lstatus);
  114. printf_P(PSTR("Since: %5d secs "), ltstatus);
  115. printf_P(PSTR("Reset: "));
  116. if (MCUSR & (1<<WDRF)) { printf_P(PSTR("Watchdog")); }
  117. if (MCUSR & (1<<BORF)) { printf_P(PSTR("Brownout")); }
  118. if (MCUSR & (1<<EXTRF)) { printf_P(PSTR("External")); }
  119. // if (MCUSR & (1<<PORF)) { printf_P(PSTR("Poweron")); } // removed by initialisation
  120. if ( ! ((MCUSR & (1<<WDRF)) | (MCUSR & (1<<BORF)) | (MCUSR & (1<<EXTRF)) | (MCUSR & (1<<PORF)))) {
  121. printf_P(PSTR("None"));
  122. }
  123. printf_P(PSTR("\r\n"));
  124. }
  125. void relay(uint8_t state) {
  126. if (state == 0) {
  127. RELAYPORT &= ~(1<<RELAYBIT);
  128. } else if (state == 1) {
  129. RELAYPORT |= (1<<RELAYBIT);
  130. }
  131. }
  132. uint16_t adcSample() {
  133. uint16_t adc = 0;
  134. uint8_t loop;
  135. // sample and discard first sample
  136. ADCSRA |= (1<<ADSC);
  137. while (ADCSRA & (1<<ADSC));
  138. for (loop = 0; loop < 16; loop++) {
  139. ADCSRA |= (1<<ADSC);
  140. while (ADCSRA & (1<<ADSC));
  141. adc += ADC;
  142. }
  143. return(adc / 16);
  144. }
  145. void calculateTemperature() {
  146. uint16_t adc = adcSample();
  147. float resistance;
  148. //printf_P(PSTR("ADC: % 3d Voltage: %1.2f\r\n"), adc, ((float)adc)*(5.0/1024));
  149. resistance = ((float)adc * (float)NTCFIXEDRES) / (1024-adc);
  150. //printf_P(PSTR("NTCRes: % 5f\r\n"), resistance);
  151. // 1 / T0 1/B R R25 K->C
  152. temperature = 1.0 / ( (1.0/298.15) + (1.0/(float)NTCBETA) * log(resistance / (float)NTCRES) ) - 273.15;
  153. }
  154. int main(void) {
  155. uint32_t ltime = 0;
  156. // set up watchdog timer
  157. wdt_enable(WDTO_8S);
  158. // set relay pin to output, set to off
  159. RELAYDDR |= (1<<RELAYBIT);
  160. relay(0);
  161. // set capacitor pin to input with pullup
  162. CAPDDR &= ~(1<<CAPBIT);
  163. CAPPORT |= (1<<CAPBIT);
  164. // set adc
  165. // attiny85 datasheet recommand 50-200kHz for maximum resolution
  166. // reference of 000 set to VCC, default to 000
  167. // ADMUX |= (1<<REFS0); // external ref
  168. ADMUX |= NTCMUX;
  169. // prescaller /128 = 62.5k = 111
  170. ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
  171. // set timer0
  172. TCCR0B |= (1<<CS02) | (1<<CS00); // /1024 prescalling
  173. TIMSK |= (1<<TOIE0); // overflow interrupt enable
  174. // set uart
  175. UARTTXDDR |= (1<<UARTTXBIT);
  176. UARTTXPORT |= (1<<UARTTXBIT);
  177. stdout = &mystdout;
  178. // power on delay, for voltage and adc stabilisation
  179. _delay_ms(1000);
  180. printf_P(PSTR("\r\n"));
  181. printf_P(PSTR("Reset! \r\n"));
  182. // turn on interrupts
  183. sei();
  184. // look if the power reset flag is set, if so reset the reset sources
  185. if (MCUSR & (1<<PORF)) {
  186. MCUSR &= ~((1<<WDRF) | (1<<BORF) | (1<<EXTRF) | (1<<PORF));
  187. }
  188. // Main loop
  189. while(1) {
  190. // wait for a second to pass
  191. while (ltime == timeSecs);
  192. ltime = timeSecs;
  193. calculateTemperature();
  194. if (status == 0) {
  195. // lock out
  196. // check for cap
  197. if ((CAPPIN & (1<<CAPBIT)) && (timeStatus >= POWERONDELAY)) {
  198. // cap is discharged, release lockout
  199. status = 1;
  200. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  201. timeStatus = 0;
  202. }
  203. }
  204. } else if (status == 1) {
  205. // Off
  206. relay(0);
  207. if (temperature >= ONTEMP) {
  208. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  209. timeStatus = 0;
  210. }
  211. status = 4;
  212. }
  213. } else if (status == 2) {
  214. // Off with delay
  215. relay(0);
  216. if (timeStatus >= OFFTIME) {
  217. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  218. timeStatus = 0;
  219. }
  220. status = 1;
  221. }
  222. } else if (status == 3) {
  223. // On
  224. relay(1);
  225. if (temperature <= OFFTEMP) {
  226. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  227. timeStatus = 0;
  228. }
  229. status = 2;
  230. }
  231. } else if (status == 4) {
  232. // On with delay
  233. relay(1);
  234. if (timeStatus >= ONTIME) {
  235. ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  236. timeStatus = 0;
  237. }
  238. status = 3;
  239. }
  240. }
  241. printData();
  242. wdt_reset();
  243. };
  244. return(0);
  245. }
  246. ISR(TIM0_OVF_vect) {
  247. // time keeping
  248. timeCycles += 262144; // 8 bits timer with /1024 prescaller
  249. if (timeCycles >= F_CPU) {
  250. timeCycles -= F_CPU;
  251. timeSecs++;
  252. timeStatus++;
  253. }
  254. }
  255.